﻿using System.Reflection;
using System.Windows.Forms;

namespace LeRenard.Libraries.Drawing.GdiPlus.Forms
{
    internal static class WindowsFormsOptimizer
    {
        /// <summary>
        /// Optimizes a <see cref="Form"/> for GDI+ drawing.
        /// </summary>
        /// <param name="form">The form to be optimized.</param>
        public static void Optimize(Form form)
        {
            // See http://www.codeproject.com/Articles/409988/Beginners-Starting-a-2D-Game-with-GDIplus

            var type = form.GetType();
            var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
            var methodInfo = type.GetMethod("SetStyle", bindingFlags);

            if (methodInfo != null) {
                object[] parameters_true = 
                {
                    // If true, the control ignores the window message WM_ERASEBKGND to reduce flicker.                    
                    ControlStyles.AllPaintingInWmPaint |                    

                    // If true, the control is first drawn to a buffer rather than directly to the screen, which can reduce flicker. 
                    // If you set this property to true, you should also set the System.Windows.Forms.ControlStyles.AllPaintingInWmPaint to true.
                    ControlStyles.OptimizedDoubleBuffer,
                    true
                };

                object[] parameters_false = 
                {
                    // If true, the control paints itself rather than the operating system doing so. 
                    // If false, the System.Windows.Forms.Control.Paint event is not raised. This style only applies to classes derived from System.Windows.Forms.Control. 
                    // So when AllPaintingInWmPaint = true and Userpaint = false then there is nobody, no aliens or other creatures in .NET telling your form to raise the paint event other than your own code.
                    ControlStyles.UserPaint,
                    false
                };

                methodInfo.Invoke(form, parameters_true);
                methodInfo.Invoke(form, parameters_false);
            }
        }
    }
}
